﻿using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using PasteTimer.HttpApi.Host.Controllers;

namespace PasteTimer
{
    /// <summary>
    /// 
    /// </summary>
    [ApiController]
    public class SlaveController : IBaseController
    {
        private ChannelHelper _channelHelper;
        private IPasteTimerDbContext _dbContext;
        private IAppCache _cache;
        private TaskConfig _config;
        private SlaveHelper _slaveHelper;
        private ModelHelper _modelHelper;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="task"></param>
        /// <param name="dbContext"></param>
        /// <param name="cache"></param>
        /// <param name="config"></param>
        /// <param name="slaveHelper"></param>
        /// <param name="modelHelper"></param>
        public SlaveController(
            ChannelHelper task,
            IPasteTimerDbContext dbContext,
            IAppCache cache,
            IOptions<TaskConfig> config,
            SlaveHelper slaveHelper,
            ModelHelper modelHelper)
        {
            _channelHelper = task;
            _dbContext = dbContext;
            _cache = cache;
            _config = config.Value;
            _slaveHelper = slaveHelper;
            _modelHelper = modelHelper;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [TypeFilter(typeof(RunModelAttribute))]
        [Route("/api/task/slave/[action]")]
        [Route("/api/slave/[action]")]
        public string info()
        {
            //checkmodel();
            var str = new System.Text.StringBuilder();
            str.AppendLine("master:");
            if (_slaveHelper.Master != null)
            {
                str.AppendLine($"{_slaveHelper.Master.id}");
            }
            else
            {
                str.AppendLine("null");
            }
            str.AppendLine("myslave:");
            str.AppendLine($"{_slaveHelper.MySlaveId}");
            return str.ToString();
        }

        /// <summary>
        /// 查找自己
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        [HttpPost]
        [TypeFilter(typeof(RunModelAttribute))]
        [Route("/api/task/slave/[action]")]
        [Route("/api/slave/[action]")]
        public string find(string guid)
        {
            if (guid == _slaveHelper.FindGuid)
            {
                return "200";
            }
            else
            {
                return "500";
            }
        }

        /// <summary>
        /// 选举 slave-->slave
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        [TypeFilter(typeof(XTokenAttribute))]
        [TypeFilter(typeof(RunModelAttribute))]
        [Route("/api/task/slave/[action]")]
        [Route("/api/slave/[action]")]
        public async Task<SlaveCallBack> vote(SlaveMaster input)
        {
            return await _slaveHelper.VoteCompare(input);
        }

        /// <summary>
        /// 客户端确认这个master是否正常
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [TypeFilter(typeof(XTokenAttribute))]
        [TypeFilter(typeof(RunModelAttribute))]
        [Route("/api/task/slave/[action]")]
        [Route("/api/slave/[action]")]
        public string link()
        {
            if (_slaveHelper.IsMaster)
            {
                return "200";
            }
            else
            {
                throw new Exception("master info error! ");
            }
        }

        /// <summary>
        /// 谁离线
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [TypeFilter(typeof(XTokenAttribute))]
        [TypeFilter(typeof(RunModelAttribute))]
        [Route("/api/task/slave/[action]")]
        [Route("/api/slave/[action]")]
        public string offline()
        {
            var fromid = CurrentSlaveId();
            if (_slaveHelper.Master != null && _slaveHelper.Master.id == fromid)
            {
                //master离线了
                //通知竞选master
                _slaveHelper.SetMaster(null);
                _channelHelper.WriteSlaveAction(new SlaveEventModel()
                {
                    Event = "votemaster",
                    Object = "",
                    FromApi = true
                });
            }
            else
            {
                //非master离线了
                //需要移除这个节点
            }
            return "ok";
        }

        /// <summary>
        /// 健康检查 slave-->master
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        [TypeFilter(typeof(RunModelAttribute))]
        [TypeFilter(typeof(XTokenAttribute))]
        [Route("/api/task/slave/[action]")]
        [Route("/api/slave/[action]")]
        public async Task<SlaveCallBack> health(SlaveHealthModel input)
        {
            if (_slaveHelper.IsMaster)
            {
                var find = _slaveHelper.SlaveUpdateTime(input.id);
                if (!find)
                {
                    var one = await _dbContext.NodeInfo.Where(x => x.Id == input.id).AsNoTracking().FirstOrDefaultAsync();
                    if (one != null && one != default)
                    {
                        _slaveHelper.SlaveAppend(new SlaveMaster()
                        {
                            id = one.Id,
                            time = System.DateTimeOffset.Now.ToUnixTimeMilliseconds(),
                            token = one.Token,
                            url = one.Url
                        });
                    }
                }
            }
            else
            {
                //对方的master信息有误
                if (_slaveHelper.Master != null)
                {
                    return new SlaveCallBack() { code = 213, message = Newtonsoft.Json.JsonConvert.SerializeObject(_slaveHelper.Master) };
                }
            }
            return new SlaveCallBack();
        }


        /// <summary>
        /// 动作事件 slave-->master
        /// </summary>
        [HttpPost]
        [TypeFilter(typeof(RunModelAttribute))]
        [TypeFilter(typeof(XTokenAttribute))]
        [Route("/api/task/slave/[action]")]
        [Route("/api/slave/[action]")]
        public SlaveCallBack action(SlaveEventModel input)
        {
            var fromslaveid = CurrentSlaveId();
            _slaveHelper.SlaveUpdateTime(fromslaveid);
            input.FromApi = true;
            _channelHelper.WriteSlaveAction(input);
            return new SlaveCallBack();
        }

        /// <summary>
        /// 消息信息 slave-->master
        /// </summary>
        [HttpPost]
        [TypeFilter(typeof(RunModelAttribute))]
        [TypeFilter(typeof(XTokenAttribute))]
        [Route("/api/task/slave/[action]")]
        [Route("/api/slave/[action]")]
        public SlaveCallBack notify(noticemodels.NoticeLogAddDto input)
        {
            var fromslaveid = CurrentSlaveId();
            _slaveHelper.SlaveUpdateTime(fromslaveid);
            _channelHelper.WriteNotice(input);
            return new SlaveCallBack();
        }


        ///// <summary>
        ///// 校验xtoken
        ///// </summary>
        ///// <returns></returns>
        ///// <exception cref="System.Exception"></exception>
        //private async Task<int> XtokenCheck()
        //{
        //    var fromid = 0;
        //    if (base.HttpContext.Request.Headers.ContainsKey("xtoken"))
        //    {
        //        var xtoken = base.HttpContext.Request.Headers["xtoken"].ToString();
        //        var strs = xtoken.Split('_');//time_fromid_toid_fromtoken_totoken
        //        int.TryParse(strs[1], out var fromslaveid);
        //        int.TryParse(strs[2], out var toslaveid);
        //        if (toslaveid != 0)
        //        {
        //            if (toslaveid == _slaveHelper.MySlaveId)
        //            {
        //                //校验token
        //                if (fromslaveid != 0)
        //                {
        //                    var fromdto = await _modelHelper.SlaveInfoDtoItem(fromslaveid);
        //                    if (fromdto != null)
        //                    {
        //                        var temptoken = $"{strs[0]}_{strs[1]}_{strs[2]}_{fromdto.Token}_{_slaveHelper.MySlaveToken}".ToMd5Lower();
        //                        if (temptoken == strs[3])
        //                        {
        //                            fromid = fromslaveid;
        //                        }
        //                    }
        //                }
        //            }
        //        }
        //    }
        //    if (fromid == 0)
        //    {
        //        throw new System.Exception("xtoken error的密钥有误，无法继续执行");
        //    }
        //    return fromid;
        //}

        ///// <summary>
        ///// 检查是否是集群模式
        ///// </summary>
        ///// <exception cref="Exception"></exception>
        //private void checkmodel()
        //{
        //    if (_config.SingleModel)
        //    {
        //        throw new Exception("System Config is Single Model Not Slave Model,Http Request Error!");
        //    }
        //    else
        //    {
        //        //校验stoken
        //        if (base.HttpContext.Request.Headers.ContainsKey("stoken"))
        //        {
        //            if(base.HttpContext.Request.Headers["stoken"].ToString() != _config.PublicToken)
        //            {
        //                throw new Exception("Header stoken Error!");
        //            }
        //        }
        //        else
        //        {
        //            throw new Exception("Header stoken Not Found, Error!");
        //        }

        //    }
        //}
    }



}
